package com.jiangyg.mall.gateway.config;

import com.jiangyg.mall.gateway.support.security.AccessAuthorizationManager;
import com.jiangyg.mall.gateway.support.security.handler.AccessDeniedExceptionHandler;
import com.jiangyg.mall.gateway.support.security.handler.AuthErrorExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;

/**
 * 类描述：安全认证
 *
 * @author jiangyg
 * @date 2022-01-08
 */
@EnableWebFluxSecurity
public class SecurityConfiguration {

    private final AccessAuthorizationManager accessAuthorizationManager;

    @Autowired
    public SecurityConfiguration(AccessAuthorizationManager accessAuthorizationManager) {
        this.accessAuthorizationManager = accessAuthorizationManager;
    }

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        // 由于前后端分离且使用JWT，所以不需要启用 CSRF
        // TODO 研究下 csrf 实现原理
        http.csrf().disable();
        // 设置不进行鉴权的地址
        final ServerHttpSecurity.AuthorizeExchangeSpec exchange = http.authorizeExchange();
        // OPTIONS 请求放行
        exchange.pathMatchers(HttpMethod.OPTIONS).permitAll();
        // 配置访问权限管理器
        exchange.anyExchange().access(accessAuthorizationManager);
        // 认证或者权限异常处理
        final ServerHttpSecurity.ExceptionHandlingSpec exceptionHandling = http.exceptionHandling();
        exceptionHandling.authenticationEntryPoint(new AuthErrorExceptionHandler());
        exceptionHandling.accessDeniedHandler(new AccessDeniedExceptionHandler());
        return http.build();
    }

}
